<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/zdh-bk/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/zdh-bk/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/zdh-bk/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/zdh-bk/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/zdh-bk/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/zdh-bk/favicon.ico?v=5.1.4">


  <link rel="mask-icon" href="/zdh-bk/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT" />





  <link rel="alternate" href="/zdh-bk/atom.xml" title="Zdh's Site" type="application/atom+xml" />






<meta property="og:type" content="website">
<meta property="og:title" content="Zdh&#39;s Site">
<meta property="og:url" content="http://antims.gitee.io/index.html">
<meta property="og:site_name" content="Zdh&#39;s Site">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Zdh&#39;s Site">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/zdh-bk/',
    scheme: 'Pisces',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://antims.gitee.io/"/>





  <title>Zdh's Site</title>
  








  <script type="text/javascript" src="/js/src/love.js"></script>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband"></div>
<a href="https://gitee.com/antims"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/zdh-bk/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Zdh's Site</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">志不强，则智不达！</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-首页">
          <a href="/zdh-bk/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-关于">
          <a href="/zdh-bk/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-标签">
          <a href="/zdh-bk/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-分类">
          <a href="/zdh-bk/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-归档">
          <a href="/zdh-bk/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>
    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://antims.gitee.io/zdh-bk/2018/01/07/sql之left join、right join、inner join的区别/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="张登辉">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/zdh-bk/uploads/huoying.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Zdh's Site">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/zdh-bk/2018/01/07/sql之left join、right join、inner join的区别/" itemprop="url">sql之left join、right join、inner join的区别</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-01-07T14:05:10+08:00">
                2018-01-07
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/zdh-bk/categories/oracle/" itemprop="url" rel="index">
                    <span itemprop="name">oracle</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <pre><code>left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 
</code></pre><p>right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录<br>inner join(等值连接) 只返回两个表中联结字段相等的行</p>
<h2 id="举例如下："><a href="#举例如下：" class="headerlink" title="举例如下： "></a>举例如下： </h2><p>表A记录如下：<br>aID　　　　　aNum<br>1　　　　　a20050111<br>2　　　　　a20050112<br>3　　　　　a20050113<br>4　　　　　a20050114<br>5　　　　　a20050115</p>
<p>表B记录如下:<br>bID　　　　　bName<br>1　　　　　2006032401<br>2　　　　　2006032402<br>3　　　　　2006032403<br>4　　　　　2006032404<br>8　　　　　2006032408</p>
<hr>
<p>1.left join<br>sql语句如下:<br>select * from A<br>left join B<br>on A.aID = B.bID</p>
<p>结果如下:<br>aID　　　　　aNum　　　　　bID　　　　　bName<br>1　　　　　a20050111　　　　1　　　　　2006032401<br>2　　　　　a20050112　　　　2　　　　　2006032402<br>3　　　　　a20050113　　　　3　　　　　2006032403<br>4　　　　　a20050114　　　　4　　　　　2006032404<br>5　　　　　a20050115　　　　NULL　　　　　NULL</p>
<p>（所影响的行数为 5 行）<br>结果说明:<br>left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.<br>换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).</p>
<h2 id="B表记录不足的地方均为NULL"><a href="#B表记录不足的地方均为NULL" class="headerlink" title="B表记录不足的地方均为NULL."></a>B表记录不足的地方均为NULL.</h2><p>2.right join<br>sql语句如下:<br>select * from A<br>right join B<br>on A.aID = B.bID</p>
<p>结果如下:<br>aID　　　　　aNum　　　　　bID　　　　　bName<br>1　　　　　a20050111　　　　1　　　　　2006032401<br>2　　　　　a20050112　　　　2　　　　　2006032402<br>3　　　　　a20050113　　　　3　　　　　2006032403<br>4　　　　　a20050114　　　　4　　　　　2006032404<br>NULL　　　　　NULL　　　　　8　　　　　2006032408</p>
<p>（所影响的行数为 5 行）<br>结果说明:</p>
<h2 id="仔细观察一下-就会发现-和left-join的结果刚好相反-这次是以右表-B-为基础的-A表不足的地方用NULL填充"><a href="#仔细观察一下-就会发现-和left-join的结果刚好相反-这次是以右表-B-为基础的-A表不足的地方用NULL填充" class="headerlink" title="仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充."></a>仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.</h2><p>3.inner join<br>sql语句如下:<br>select * from A<br>innerjoin B<br>on A.aID = B.bID</p>
<p>结果如下:<br>aID　　　　　aNum　　　　　bID　　　　　bName<br>1　　　　　a20050111　　　　1　　　　　2006032401<br>2　　　　　a20050112　　　　2　　　　　2006032402<br>3　　　　　a20050113　　　　3　　　　　2006032403<br>4　　　　　a20050114　　　　4　　　　　2006032404</p>
<p>结果说明:</p>
<h2 id="很明显-这里只显示出了-A-aID-B-bID的记录-这说明inner-join并不以谁为基础-它只显示符合条件的记录"><a href="#很明显-这里只显示出了-A-aID-B-bID的记录-这说明inner-join并不以谁为基础-它只显示符合条件的记录" class="headerlink" title="很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录."></a>很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.</h2><p>注:<br>LEFT JOIN操作用于在任何的 FROM 子句中，组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联接将包含了从第一个（左边）开始的两个表中的全部记录，即使在第二个（右边）表中并没有相符值的记录。</p>
<p>语法：FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2</p>
<p>说明：table1, table2参数用于指定要将记录组合的表的名称。<br>field1, field2参数指定被联接的字段的名称。且这些字段必须有相同的数据类型及包含相同类型的数据，但它们不需要有相同的名称。<br>compopr参数指定关系比较运算符：”=”， “&lt;”， “&gt;”， “&lt;=”， “&gt;=” 或 “&lt;&gt;”。<br>如果在INNER JOIN操作中要联接包含Memo 数据类型或 OLE Object 数据类型数据的字段，将会发生错误. </p>

          
        
      
    </div>
    
    
    
<div>
  
</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://antims.gitee.io/zdh-bk/2018/01/07/状态模式/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="张登辉">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/zdh-bk/uploads/huoying.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Zdh's Site">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/zdh-bk/2018/01/07/状态模式/" itemprop="url">状态模式</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-01-07T14:01:00+08:00">
                2018-01-07
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/zdh-bk/categories/设计模式/" itemprop="url" rel="index">
                    <span itemprop="name">设计模式</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p> 在介绍状态模式之前，我们先来看这样一个实例：你公司力排万难终于获得某个酒店的系统开发项目，并且最终落到了你的头上。下图是他们系统的主要工作(够简单)。</p>
<p>图片1</p>
<pre><code>当你第一眼看到这个系统的时候你就看出来了这是一个状态图，每个框框都代表了房间的状态，箭头表示房间状态的转换。分析如下：房间有三个状态：空闲、已预订、已入住，状态与状态之间可以根据客户的动作来进行转换。定义每个状态的值。
</code></pre><p>public static final int FREEMTIME_STATE = 0;  //空闲状态<br>    public static final int BOOKED_STATE = 1;     //已预订状态<br>    public static final int CHECKIN_STATE = 2;    //入住状态</p>
<pre><code>int state = FREEMTIME_STATE;     //初始状态
  通过客户的动作将每个状态整合起来，对于这个“最简单”的方式肯定是if…else if…else啦！所以这里我们就通过动作将所有的状态全面整合起来。分析得这里有四个动作：预订、入住、退订、退房。如下：
</code></pre><p>/**</p>
<pre><code> * @desc 预订
 * @return void
 */
public void bookRoom(){
    if(state == FREEMTIME_STATE){   //空闲可预订
        if(count &gt; 0){
            System.out.println(&quot;空闲房间，完成预订...&quot;);
            state =  BOOKED_STATE;     //改变状态：已预订
            count --;
            //房间预订完了,提示客户没有房源了
            if(count == 0){
                System.out.println(&quot;不好意思,房间已经预订完,欢迎您下次光临...&quot;);
            }
        }
        else{
            System.out.println(&quot;不好意思,已经没有房间了....&quot;);
        }
    }
    else if(state == BOOKED_STATE){
        System.out.println(&quot;该房间已经被预订了...&quot;);
    }
    else if(state == CHECKIN_STATE){
        System.out.println(&quot;该房间已经有人入住了...&quot;);
    }
}

/**
 * @desc 入住
 * @return void
 */
public void checkInRoom(){
    if(state == FREEMTIME_STATE){
        if(count &gt; 0){
            System.out.println(&quot;空闲房间，入住...&quot;);
            state =  CHECKIN_STATE;     //改变状态：已预订
            count --;
            //房间预订完了,提示客户没有房源了
            if(count == 0){
                System.out.println(&quot;不好意思,房间已经预订完,欢迎您下次光临...&quot;);
            }
        }
        else{
            System.out.println(&quot;不好意思,已经没有房间了....&quot;);
        }

    }
    else if(state == BOOKED_STATE){
        if(&quot;如果该房间是您预订的&quot;){
            System.out.println(&quot;入住....&quot;);
            state = CHECKIN_STATE;
        }
        else{
            System.out.println(&quot;您没有预订该房间,请先预订...&quot;);
        }
    }
    else if(state == CHECKIN_STATE){
        System.out.println(&quot;该房间已经入住了...&quot;);
    }
}

/**
 * @desc 退订
 * @return void
 */
public void unsubscribeRoom(){
    if(state == FREEMTIME_STATE){
    }
    else if(state == CHECKIN_STATE){

    }
    else if(state == BOOKED_STATE){
        System.out.println(&quot;已退订房间...&quot;);
        state = FREEMTIME_STATE;
        count ++;
    }
}

/**
 * @desc 退房
 * @return void
 */
public void checkOutRoom(){
    if(state == FREEMTIME_STATE){

    }
    else if(state == BOOKED_STATE){

    }
    else if(state == CHECKIN_STATE){
        System.out.println(&quot;已退房..&quot;);
        state = FREEMTIME_STATE;
        count++;
    }
}
  对于上面的代码你是否满意呢？满意那么你就没有必要往下看了，不满意我们接着讲。

  正当你完成这个“复杂”if..else if …else时(我都写了一会儿)，你客户说，我们需要将某些房间保留下来以作为备用(standbyState)，于是你发现你悲剧了，因为你发现你要在所有的操作里都要判断该房间是否为备用房间。当你老大经过你身边的时候发现你正在纠结怎么改的时候，你老大就问你为什么不换一个角度思考以状态为原子来改变它的行为，而不是通过行为来改变状态呢？于是你就学到了状态模式。
</code></pre><p>一、模式定义</p>
<pre><code>在很多情况下，一个对象的行为取决于它的一个或多个变化的属性，这些属性我们称之为状态，这个对象称之为状态对象。对于状态对象而已，它的行为依赖于它的状态，比如你要预订房间，那么只有当该房间为空闲时你才能预订，你想入住该房间也只有当你预订了该房间或者该房间为空闲时。对于这样的一个对象，当它在于外部事件产生互动的时候，其内部状态就会发生改变，从而使得他的行为也随之发生改变。

那么何为状态模式呢？所谓状态模式就是允许对象在内部状态发生改变时改变它的行为，对象看起来好像修改了它的类。
</code></pre><p>二、模式结构</p>
<pre><code>下图为状态模式的UML图。
</code></pre><p>图片2</p>
<pre><code>状态模式包含如下角色：

   Context: 环境类。可以包括一些内部状态。

   State: 抽象状态类。State定义了一个所有具体状态的共同接口，任何状态都实现这个相同的接口，这样一来，状态之间就可以互相转换了。

   ConcreteState: 具体状态类。具体状态类，用于处理来自Context的请求，每一个ConcreteState都提供了它对自己请求的实现，所以，当Context改变状态时行为也会跟着改变。
</code></pre><p>三、模式实现</p>
<pre><code>依然是上面那个酒店的实例。对于该实例的UML图如下：
</code></pre><p>aaaa</p>
<pre><code>首先是状态接口：State
</code></pre><p>public interface State {<br>    /**</p>
<pre><code> * @desc 预订房间
 * @return void
 */
public void bookRoom();

/**
 * @desc 退订房间
 * @return void
 */
public void unsubscribeRoom();

/**
 * @desc 入住
 * @return void
 */
public void checkInRoom();

/**
 * @desc 退房
 * @return void
 */
public void checkOutRoom();
</code></pre><p>}<br>      然后是房间类</p>
<p>public class Room {<br>    /*</p>
<pre><code> * 房间的三个状态
 */
State freeTimeState;    //空闲状态
State checkInState;     //入住状态
State bookedState;      //预订状态

State state ;  

public Room(){
    freeTimeState = new FreeTimeState(this);
    checkInState = new CheckInState(this);
    bookedState = new BookedState(this);

    state = freeTimeState ;  //初始状态为空闲
}

/**
 * @desc 预订房间
 * @return void
 */
public void bookRoom(){
    state.bookRoom();
}

/**
 * @desc 退订房间
 * @return void
 */
public void unsubscribeRoom(){
    state.unsubscribeRoom();
}

/**
 * @desc 入住
 * @return void
 */
public void checkInRoom(){
    state.checkInRoom();
}

/**
 * @desc 退房
 * @return void
 */
public void checkOutRoom(){
    state.checkOutRoom();
}

public String toString(){
    return &quot;该房间的状态是:&quot;+getState().getClass().getName();
}

/*
 * getter和setter方法
 */

public State getFreeTimeState() {
    return freeTimeState;
}

public void setFreeTimeState(State freeTimeState) {
    this.freeTimeState = freeTimeState;
}

public State getCheckInState() {
    return checkInState;
}

public void setCheckInState(State checkInState) {
    this.checkInState = checkInState;
}

public State getBookedState() {
    return bookedState;
}

public void setBookedState(State bookedState) {
    this.bookedState = bookedState;
}

public State getState() {
    return state;
}

public void setState(State state) {
    this.state = state;
}
</code></pre><p>}<br>      然后是3个状态类,这个三个状态分别对于这:空闲、预订、入住。其中空闲可以完成预订和入住两个动作，预订可以完成入住和退订两个动作，入住可以退房。</p>
<p>/** </p>
<ul>
<li>@project: design_state </li>
<li>@author chenssy</li>
<li>@date 2013-8-24 </li>
<li><p>@Description: 空闲状态只能预订和入住<br>*/<br>public class FreeTimeState implements State {</p>
<p> Room hotelManagement;</p>
<p> public FreeTimeState(Room hotelManagement){</p>
<pre><code>this.hotelManagement = hotelManagement;
</code></pre><p> }</p>
</li>
</ul>
<pre><code>public void bookRoom() {
    System.out.println(&quot;您已经成功预订了...&quot;);
    hotelManagement.setState(hotelManagement.getBookedState());   //状态变成已经预订
}

public void checkInRoom() {
    System.out.println(&quot;您已经成功入住了...&quot;);
    hotelManagement.setState(hotelManagement.getCheckInState());   //状态变成已经入住
}

public void checkOutRoom() {
    //不需要做操作
}

public void unsubscribeRoom() {
    //不需要做操作
}
</code></pre><p>}</p>
<p>/** </p>
<ul>
<li>@project: design_state </li>
<li>@author chenssy</li>
<li>@date 2013-8-24 </li>
<li><p>@Description: 入住状态房间只能退房<br>*/<br>public class BookedState implements State {<br> Room hotelManagement;</p>
<p> public BookedState(Room hotelManagement) {</p>
<pre><code>this.hotelManagement = hotelManagement;
</code></pre><p> }</p>
<p> public void bookRoom() {</p>
<pre><code>System.out.println(&quot;该房间已近给预定了...&quot;);
</code></pre><p> }</p>
<p> public void checkInRoom() {</p>
<pre><code>System.out.println(&quot;入住成功...&quot;); 
hotelManagement.setState(hotelManagement.getCheckInState());         //状态变成入住
</code></pre><p> }</p>
<p> public void checkOutRoom() {</p>
<pre><code>//不需要做操作
</code></pre><p> }</p>
<p> public void unsubscribeRoom() {</p>
<pre><code>System.out.println(&quot;退订成功,欢迎下次光临...&quot;);
hotelManagement.setState(hotelManagement.getFreeTimeState());   //变成空闲状态
</code></pre><p> }</p>
</li>
</ul>
<p>}</p>
<p>/** </p>
<ul>
<li>@project: design_state </li>
<li>@author chenssy</li>
<li>@date 2013-8-24 </li>
<li><p>@Description: 入住可以退房<br>*/<br>public class CheckInState implements State {<br> Room hotelManagement;<br> public CheckInState(Room hotelManagement) {</p>
<pre><code>this.hotelManagement = hotelManagement;
</code></pre><p> }</p>
<p> public void bookRoom() {</p>
<pre><code>System.out.println(&quot;该房间已经入住了...&quot;);
</code></pre><p> }</p>
<p> public void checkInRoom() {</p>
<pre><code>System.out.println(&quot;该房间已经入住了...&quot;);
</code></pre><p> }</p>
<p> public void checkOutRoom() {</p>
<pre><code>System.out.println(&quot;退房成功....&quot;);
hotelManagement.setState(hotelManagement.getFreeTimeState());     //状态变成空闲
</code></pre><p> }</p>
<p> public void unsubscribeRoom() {</p>
<pre><code>//不需要做操作
</code></pre><p> }</p>
</li>
</ul>
<p>}<br>      最后是测试类</p>
<p>public class Test {<br>    public static void main(String[] args) {<br>        //有3间房<br>        Room[] rooms = new Room[2];<br>        //初始化<br>        for(int i = 0 ; i &lt; rooms.length ; i++){<br>            rooms[i] = new Room();<br>        }<br>        //第一间房<br>        rooms[0].bookRoom();    //预订<br>        rooms[0].checkInRoom();   //入住<br>        rooms[0].bookRoom();    //预订<br>        System.out.println(rooms[0]);<br>        System.out.println(“—————————“);</p>
<pre><code>    //第二间房
    rooms[1].checkInRoom();
    rooms[1].bookRoom();
    rooms[1].checkOutRoom();
    rooms[1].bookRoom();
    System.out.println(rooms[1]);
}
</code></pre><p>}</p>
<pre><code>运行结果
</code></pre><p>1111</p>
<p>四、模式优缺点</p>
<p>优点</p>
<pre><code>1、封装了转换规则。

2、枚举可能的状态，在枚举状态之前需要确定状态种类。

3、将所有与某个状态有关的行为放到一个类中，并且可以方便地增加新的状态，只需要改变对象状态即可改变对象的行为。

4、允许状态转换逻辑与状态对象合成一体，而不是某一个巨大的条件语句块。

5、可以让多个环境对象共享一个状态对象，从而减少系统中对象的个数。
</code></pre><p>缺点</p>
<pre><code>1、状态模式的使用必然会增加系统类和对象的个数。

2、状态模式的结构与实现都较为复杂，如果使用不当将导致程序结构和代码的混乱。

3、状态模式对“开闭原则”的支持并不太好，对于可以切换状态的状态模式，增加新的状态类需要修改那些负责状态转换的源代码，否则无法切换到新增状态；而且修改某个状态类的行为也需修改对应类的源代码。
</code></pre><p>五、模式适用场景</p>
<pre><code>1、对象的行为依赖于它的状态（属性）并且可以根据它的状态改变而改变它的相关行为。

2、代码中包含大量与对象状态有关的条件语句
</code></pre><p>六、模式总结</p>
<pre><code>1、状态模式允许一个对象基于内部状态而拥有不同的行为。

2、Context会将行为委托给当前状态对象。

3、状态模式对“开闭原则”支持不是很好。
</code></pre>
          
        
      
    </div>
    
    
    
<div>
  
</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://antims.gitee.io/zdh-bk/2018/01/07/桥梁模式/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="张登辉">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/zdh-bk/uploads/huoying.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Zdh's Site">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/zdh-bk/2018/01/07/桥梁模式/" itemprop="url">桥梁模式</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-01-07T14:00:00+08:00">
                2018-01-07
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/zdh-bk/categories/设计模式/" itemprop="url" rel="index">
                    <span itemprop="name">设计模式</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>在阎宏博士的《JAVA与模式》一书中开头是这样描述桥梁（Bridge）模式的：</p>
<p>　　桥梁模式是对象的结构模式。又称为柄体(Handle and Body)模式或接口(Interface)模式。桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦，使得二者可以独立地变化”。</p>
<p>桥梁模式的用意<br>　　桥梁模式虽然不是一个使用频率很高的模式，但是熟悉这个模式对于理解面向对象的设计原则，包括“开-闭”原则以及组合/聚合复用原则都很有帮助。理解好这两个原则，有助于形成正确的设计思想和培养良好的设计风格。</p>
<p>　　桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦，使得二者可以独立地变化”。这句话很短，但是第一次读到这句话的人很可能都会思考良久而不解其意。</p>
<p>　　这句话有三个关键词，也就是抽象化、实现化和脱耦。理解这三个词所代表的概念是理解桥梁模式用意的关键。</p>
<p>　　抽象化<br>　　从众多的事物中抽取出共同的、本质性的特征，而舍弃其非本质的特征，就是抽象化。例如苹果、香蕉、生梨、 桃子等，它们共同的特性就是水果。得出水果概念的过程，就是一个抽象化的过程。要抽象，就必须进行比较，没有比较就无法找到在本质上共同的部分。共同特征是指那些能把一类事物与他类事物区分开来的特征，这些具有区分作用的特征又称本质特征。因此抽取事物的共同特征就是抽取事物的本质特征，舍弃非本质的特征。 所以抽象化的过程也是一个裁剪的过程。在抽象时，同与不同，决定于从什么角度上来抽象。抽象的角度取决于分析问题的目的。</p>
<p>　　通常情况下，一组对象如果具有相同的特征，那么它们就可以通过一个共同的类来描述。如果一些类具有相同的特征，往往可以通过一个共同的抽象类来描述。</p>
<p>　　实现化<br>　　抽象化给出的具体实现，就是实现化。</p>
<p>　　一个类的实例就是这个类的实例化，一个具体子类是它的抽象超类的实例化。</p>
<p>　　脱耦<br>　　所谓耦合，就是两个实体的行为的某种强关联。而将它们的强关联去掉，就是耦合的解脱，或称脱耦。在这里，脱耦是指将抽象化和实现化之间的耦合解脱开，或者说是将它们之间的强关联改换成弱关联。</p>
<p>　　所谓强关联，就是在编译时期已经确定的，无法在运行时期动态改变的关联；所谓弱关联，就是可以动态地确定并且可以在运行时期动态地改变的关联。显然，在Java语言中，继承关系是强关联，而聚合关系是弱关联。</p>
<p>　　将两个角色之间的继承关系改为聚合关系，就是将它们之间的强关联改换成为弱关联。因此，桥梁模式中的所谓脱耦，就是指在一个软件系统的抽象化和实现化之间使用聚合关系而不是继承关系，从而使两者可以相对独立地变化。这就是桥梁模式的用意。</p>
<p>桥梁模式的结构<br>　　下图所示就是一个实现了桥梁模式的示意性系统的结构图：</p>
<p>　　可以看出，这个系统含有两个等级结构：</p>
<p>　　一、由抽象化角色和修正抽象化角色组成的抽象化等级结构。</p>
<p>　　二、由实现化角色和两个具体实现化角色所组成的实现化等级结构。</p>
<p>　　桥梁模式所涉及的角色有：</p>
<p>　　●　　抽象化(Abstraction)角色：抽象化给出的定义，并保存一个对实现化对象的引用。</p>
<p>　　●　　修正抽象化(RefinedAbstraction)角色：扩展抽象化角色，改变和修正父类对抽象化的定义。</p>
<p>　　●　　实现化(Implementor)角色：这个角色给出实现化角色的接口，但不给出具体的实现。必须指出的是，这个接口不一定和抽象化角色的接口定义相同，实际上，这两个接口可以非常不一样。实现化角色应当只给出底层操作，而抽象化角色应当只给出基于底层操作的更高一层的操作。</p>
<p>　　●　　具体实现化(ConcreteImplementor)角色：这个角色给出实现化角色接口的具体实现。</p>
<p>　　抽象化角色就像是一个水杯的手柄，而实现化角色和具体实现化角色就像是水杯的杯身。手柄控制杯身，这就是此模式别名“柄体”的来源。</p>
<p>　　对象是对行为的封装，而行为是由方法实现的。在这个示意性系统里，抽象化等级结构中的类封装了operation()方法；而实现化等级结构中的类封装的是operationImpl()方法。当然，在实际的系统中往往会有多于一个的方法。</p>
<p>　　抽象化等级结构中的方法通过向对应的实现化对象的委派实现自己的功能，这意味着抽象化角色可以通过向不同的实现化对象委派，来达到动态地转换自己的功能的目的。</p>
<p>源代码</p>
<p>　　抽象化角色类，它声明了一个方法operation()，并给出了它的实现。这个实现是通过向实现化对象的委派(调用operationImpl()方法)实现的。</p>
<p>复制代码<br>public abstract class Abstraction {</p>
<pre><code>protected Implementor impl;

public Abstraction(Implementor impl){
    this.impl = impl;
}
//示例方法
public void operation(){

    impl.operationImpl();
}
</code></pre><p>}<br>复制代码<br>　　修正抽象化角色</p>
<p>复制代码<br>public class RefinedAbstraction extends Abstraction {</p>
<pre><code>public RefinedAbstraction(Implementor impl) {
    super(impl);
}
//其他的操作方法
public void otherOperation(){

}
</code></pre><p>}<br>复制代码<br>　　实现化角色</p>
<p>复制代码<br>public abstract class Implementor {<br>    /**</p>
<pre><code> * 示例方法，实现抽象部分需要的某些具体功能
 */
public abstract void operationImpl();
</code></pre><p>}<br>复制代码<br>　　具体实现化角色</p>
<p>复制代码<br>public class ConcreteImplementorA extends Implementor {</p>
<pre><code>@Override
public void operationImpl() {
    //具体操作
}
</code></pre><p>}<br>复制代码<br>复制代码<br>public class ConcreteImplementorB extends Implementor {</p>
<pre><code>@Override
public void operationImpl() {
    //具体操作
}
</code></pre><p>}<br>复制代码<br>　　一般而言，实现化角色中的每个方法都应当有一个抽象化角色中的某一个方法与之对应，但是反过来则不一定。换言之，抽象化角色的接口比实现化角色的接口宽。抽象化角色除了提供与实现化角色相关的方法之外，还有可能提供其他的方法；而实现化角色则往往仅为实现抽象化角色的相关行为而存在。</p>
<p>使用场景<br>　　考虑这样一个实际的业务功能：发送提示消息。基本上所有带业务流程处理的系统都会有这样的功能，比如OA上有尚未处理完毕的文件，需要发送一条消息提示他。</p>
<p>　　从业务上看，消息又分成普通消息、加急消息和特急消息多种，不同的消息类型，业务功能处理是不一样的，比如加急消息是在消息上添加加急，而特急消息除了添加特急外，还会做一条催促的记录，多久不完成会继续催促；从发送消息的手段上看，又有系统内短消息、手机短信息、邮件等。</p>
<p>不使用模式的解决方案</p>
<p>　实现发送普通消息<br>　　先考虑实现一个简单点的版本，比如，消息只是实现发送普通消息，发送的方式只实现系统内短消息和邮件。其他的功能，等这个版本完成后，再继续添加。</p>
<p>源代码</p>
<p>　　消息的统一接口</p>
<p>复制代码<br>public interface Message {<br>    /**</p>
<pre><code> * 发送消息
 * @param message 要发送消息的内容
 * @param toUser  消息的接受者
 */
public void send(String message , String toUser);
</code></pre><p>}<br>复制代码<br>　　系统内短消息示例类</p>
<p>复制代码<br>public class CommonMessageSMS implements Message {</p>
<pre><code>@Override
public void send(String message, String toUser) {

    System.out.println(&quot;使用系统内短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　　邮件消息示例类</p>
<p>复制代码<br>public class CommonMessageEmail implements Message{</p>
<pre><code>@Override
public void send(String message, String toUser) {

    System.out.println(&quot;使用邮件短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　实现发送加急消息<br>　　发送加急消息同样有两种方式，系统内短消息和邮件方式。但是加急消息的实现不同于普通消息，加急消息会自动在消息上添加加急，然后在再发送消息；另外加急消息会提供监控的方法，让客户端可以随时通过这个方法来了解对于加急消息的处理进度。比如，相应的人员是否接收到这个信息，相应的处理工作是否已经展开。因此加急消息需要扩展出一个新的接口，除了基本的发送消息的功能，还需要添加监控功能。</p>
<p>源代码</p>
<p>　　加急消息的接口</p>
<p>复制代码<br>public interface UrgencyMessage extends Message {<br>    /**</p>
<pre><code> * 监控指定消息的处理过程
 * @param messageId  被监控的消息编号
 * @return    监控到的消息的处理状态
 */
public Object watch(String messageId);
</code></pre><p>}<br>复制代码<br>　　系统内加急短消息示例类</p>
<p>复制代码<br>public class UrgencyMessageSMS implements UrgencyMessage {</p>
<pre><code>@Override
public Object watch(String messageId) {
    // 根据消息id获取消息的状态，组织成监控的数据对象，然后返回
    return null;
}

@Override
public void send(String message, String toUser) {

    message = &quot;加急：&quot; + message;
    System.out.println(&quot;使用系统内短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　　邮件加急短消息示例类</p>
<p>复制代码<br>public class UrgencyMessageEmail implements UrgencyMessage {</p>
<pre><code>@Override
public Object watch(String messageId) {
    // 根据消息id获取消息的状态，组织成监控的数据对象，然后返回
    return null;
}

@Override
public void send(String message, String toUser) {

    message = &quot;加急：&quot; + message;
    System.out.println(&quot;使用邮件短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　实现发送特急消息<br>　　特急消息不需要查看处理进程，只有没有完成，就直接催促，也就是说，对于特急消息，在普通消息的处理基础上，需要添加催促的功能。</p>
<p>　　观察上面的系统结构图，会发现一个很明显的问题，那就是通过这种继承的方式来扩展消息处理，会非常不方便。实现加急消息处理的时候，必须实现系统内短消息和邮件两种处理方式，因为业务处理可能不同，在实现特急消息处理的时候，又必须实现系统内短信息和邮件两种处理方式。这意味着，以后每次扩展一下消息处理，都必须要实现这两种处理方式，这还不算完，如果要添加新的实现方式呢？</p>
<p>　添加发送手机消息的处理方式<br>　　如果要添加一种新的发送消息的方式，是需要在每一种抽象的具体实现中，都添加发送手机消息的处理的。也就是说，发送普通消息、加急消息和特急消息的处理，都可以通过手机来发送。</p>
<p>　　<br>　　采用通过继承来扩展的实现方式，有个明显的缺点，扩展消息的种类不太容易。不同种类的消息具有不同的业务，也就是有不同的实现，在这种情况下，每一种类的消息，需要实现所有不同的消息发送方式。更可怕的是，如果要新加入一种消息的发送方式，那么会要求所有的消息种类都有加入这种新的发送方式的实现。</p>
<p>　　那么究竟该如何才能既实现功能，又可以灵活地扩展呢？</p>
<p>使用桥梁模式来解决问题<br>　　根据业务的功能要求，业务的变化具有两个维度，一个维度是抽象的消息，包括普通消息、加急消息和特急消息，这几个抽象的消息本身就具有一定的关系，加急消息和特急消息会扩展普通消息；另一个维度是在具体的消息发送方式上，包括系统内短消息、邮件和手机短消息，这几个方式是平等的，可被切换的方式。</p>
<p>　　</p>
<p>　　</p>
<p>　　现在出现问题的根本原因，就在于消息的抽象和实现是混杂在一起的，这就导致了一个纬度的变化会引起另一个纬度进行相应的变化，从而使得程序扩展起来非常困难。</p>
<p>　　要想解决这个问题，就必须把这两个纬度分开，也就是将抽象部分和实现部分分开，让它们相互独立，这样就可以实现独立的变化，使扩展变得简单。抽象部分就是各个消息的类型所对应的功能，而实现部分就是各种发送消息的方式。按照桥梁模式的结构，给抽象部分和实现部分分别定义接口，然后分别实现它们就可以了。</p>
<p>　　</p>
<p>　源代码</p>
<p>　　抽象消息类</p>
<p>复制代码<br>public abstract class AbstractMessage {<br>    //持有一个实现部分的对象<br>    MessageImplementor impl;<br>    /**</p>
<pre><code> * 构造方法，传入实现部分的对象
 * @param impl  实现部分的对象
 */
public AbstractMessage(MessageImplementor impl){
    this.impl = impl;
}
/**
 * 发送消息，委派给实现部分的方法
 * @param message    要发送消息的内容
 * @param toUser    消息的接受者
 */
public void sendMessage(String message , String toUser){
    this.impl.send(message, toUser);
}
</code></pre><p>}<br>复制代码</p>
<p>　　普通消息类</p>
<p>复制代码<br>public class CommonMessage extends AbstractMessage {</p>
<pre><code>public CommonMessage(MessageImplementor impl) {
    super(impl);
}
@Override
public void sendMessage(String message, String toUser) {
    // 对于普通消息，直接调用父类方法，发送消息即可
    super.sendMessage(message, toUser);
}
</code></pre><p>}<br>复制代码<br>　　加急消息类</p>
<p>复制代码<br>public class UrgencyMessage extends AbstractMessage {</p>
<pre><code>public UrgencyMessage(MessageImplementor impl) {
    super(impl);
}
@Override
public void sendMessage(String message, String toUser) {
    message = &quot;加急：&quot; + message;
    super.sendMessage(message, toUser);
}
/**
 * 扩展自己的新功能，监控某消息的处理状态
 * @param messageId    被监控的消息编号
 * @return    监控到的消息的处理状态
 */
public Object watch(String messageId) {
    // 根据消息id获取消息的状态，组织成监控的数据对象，然后返回
    return null;
}
</code></pre><p>}<br>复制代码<br>　　实现发送消息的统一接口</p>
<p>复制代码<br>public interface MessageImplementor {<br>    /**</p>
<pre><code> * 发送消息
 * @param message 要发送消息的内容
 * @param toUser  消息的接受者
 */
public void send(String message , String toUser);
</code></pre><p>}<br>复制代码<br>　　系统内短消息的实现类</p>
<p>复制代码<br>public class MessageSMS implements MessageImplementor {</p>
<pre><code>@Override
public void send(String message, String toUser) {

    System.out.println(&quot;使用系统内短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　　邮件短消息的实现类</p>
<p>复制代码<br>public class MessageEmail implements MessageImplementor {</p>
<pre><code>@Override
public void send(String message, String toUser) {
    System.out.println(&quot;使用邮件短消息的方法，发送消息&apos;&quot;+message+&quot;&apos;给&quot;+toUser);
}
</code></pre><p>}<br>复制代码<br>　　客户端类</p>
<p>复制代码<br>public class Client {</p>
<pre><code>public static void main(String[] args) {
    //创建具体的实现对象
    MessageImplementor impl = new MessageSMS();
    //创建普通消息对象
    AbstractMessage message = new  CommonMessage(impl);
    message.sendMessage(&quot;加班申请速批&quot;,&quot;李总&quot;);

    //将实现方式切换成邮件，再次发送
    impl = new MessageEmail();
    //创建加急消息对象
    message = new UrgencyMessage(impl);
    message.sendMessage(&quot;加班申请速批&quot;,&quot;李总&quot;);
}
</code></pre><p>}<br>复制代码<br>　　观察上面的例子会发现，采用桥梁模式来实现，抽象部分和实现部分分离开了，可以相互独立的变化，而不会相互影响。因此在抽象部分添加新的消息处理（特急消息），对发送消息的实现部分是没有影响的；反过来增加发送消息的方式（手机短消息），对消息处理部分也是没有影响的。</p>
<p>桥梁模式的优点<br>　　●　　分离抽象和实现部分</p>
<p>　　桥梁模式分离了抽象部分和实现部分，从而极大地提供了系统的灵活性。让抽象部分和实现部分独立出来，分别定义接口，这有助于对系统进行分层，从而产生更好的结构化的系统。</p>
<p>　　●　　更好的扩展性</p>
<p>　　桥梁模式使得抽象部分和实现部分可以分别独立地扩展，而不会相互影响，从而大大提高了系统的可扩展性。</p>
<p>桥梁模式在Java中的使用<br>　　桥梁模式在Java应用中的一个非常典型的例子就是JDBC驱动器。JDBC为所有的关系型数据库提供一个通用的界面。一个应用系统动态地选择一个合适的驱动器，然后通过驱动器向数据库引擎发出指令。这个过程就是将抽象角色的行为委派给实现角色的过程。</p>
<p>　　抽象角色可以针对任何数据库引擎发出查询指令，因为抽象角色并不直接与数据库引擎打交道，JDBC驱动器负责这个底层的工作。由于JDBC驱动器的存在，应用系统可以不依赖于数据库引擎的细节而独立地演化；同时数据库引擎也可以独立于应用系统的细节而独立的演化。两个独立的等级结构如下图所示，左边是JDBC API的等级结构，右边是JDBC驱动器的等级结构。应用程序是建立在JDBC API的基础之上的。</p>
<p>　　应用系统作为一个等级结构，与JDBC驱动器这个等级结构是相对独立的，它们之间没有静态的强关联。应用系统通过委派与JDBC驱动器相互作用，这是一个桥梁模式的例子。</p>
<p>　　JDBC的这种架构，把抽象部分和具体部分分离开来，从而使得抽象部分和具体部分都可以独立地扩展。对于应用程序而言，只要选用不同的驱动，就可以让程序操作不同的数据库，而无需更改应用程序，从而实现在不同的数据库上移植；对于驱动程序而言，为数据库实现不同的驱动程序，并不会影响应用程序。</p>

          
        
      
    </div>
    
    
    
<div>
  
</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  


          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/zdh-bk/uploads/huoying.jpg"
                alt="张登辉" />
            
              <p class="site-author-name" itemprop="name">张登辉</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/zdh-bk/archives">
              
                  <span class="site-state-item-count">3</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/zdh-bk/categories/index.html">
                  <span class="site-state-item-count">2</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/zdh-bk/tags/index.html">
                  <span class="site-state-item-count">2</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/zdh-bk/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://gitee.com/antims" target="_blank" title="码云">
                      
                        <i class="fa fa-fw fa-github"></i>码云</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="http://blog.csdn.net/qq_29347295" target="_blank" title="csdn">
                      
                        <i class="fa fa-fw fa-cab"></i>csdn</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">张登辉</span>

  
</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/zdh-bk/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/zdh-bk/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/zdh-bk/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/zdh-bk/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/zdh-bk/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/zdh-bk/js/src/schemes/pisces.js?v=5.1.4"></script>



  

  


  <script type="text/javascript" src="/zdh-bk/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  
    

    
  





  












  





  

  

  

  
  

  

  

  

</body>
<script type="text/javascript" src="/js/src/love.js"></script>
</html>
